package com.health.yb.web.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.health.yb.core.exception.CommonException;
import com.health.yb.core.utils.MapperFactoryUtil;
import com.health.yb.web.bean.common.Response;
import com.health.yb.web.bean.entity.YbType;
import com.health.yb.web.bean.entity.YbUser;
import com.health.yb.web.bean.entity.YbUserInfo;
import com.health.yb.web.bean.req.UserMaterialReq;
import com.health.yb.web.bean.req.YbUserAddReq;
import com.health.yb.web.bean.req.YbUserReq;
import com.health.yb.web.bean.res.YbUserRes;
import com.health.yb.web.mapper.UserInfoMapper;
import com.health.yb.web.mapper.YbTypeMapper;
import com.health.yb.web.mapper.YbUserMapper;
import com.health.yb.web.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author rjwang
 * @version 1.0
 * @date 2019/12/17 20:35
 */
@Service
@Transactional(isolation = Isolation.REPEATABLE_READ,rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<YbUserMapper, YbUser> implements UserService {

    @Autowired
    YbUserMapper ybUserMapper;
    @Autowired
    YbTypeMapper ybTypeMapper;
    @Autowired
    private UserInfoMapper userInfoMapper;


    @Override
    public Response addUserType(YbUserAddReq ybUserAddReq) {
        //系统创建时间
        LocalDateTime now = LocalDateTime.now();
        //领取物品时间
        String needDate = ybUserAddReq.getNeedDate();
        //用户名称
        Long userId = ybUserAddReq.getUserId();
        List<YbUserReq> userTypes = ybUserAddReq.getUserTypes();
        List<YbUser> ybUsers = MapperFactoryUtil.beanLTtoLC(userTypes, YbUser.class);
//        List<YbUser> ybUsers = MapperFactoryUtil.beanLTtoLC(userTypes, YbUser.class);
        //设置领取用户、创建时间、领取时间
        ybUsers.forEach(user->{
            user.setCreateDate(now.toString());
            user.setNeedDate(needDate);
            user.setUserId(userId);
        });
        this.saveBatch(ybUsers);
        return new Response().successWithMsg("添加物资成功");
    }

    @Override
    public void exportStatiesData(String startDate, String endDate, HttpServletRequest request, HttpServletResponse response) throws Exception {
        LambdaQueryWrapper<YbUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(startDate)) {
            lambdaQueryWrapper.ge(YbUser::getNeedDate, startDate);
        }
        if (StrUtil.isNotBlank(endDate)) {
            lambdaQueryWrapper.le(YbUser::getNeedDate, endDate);
        }
        //根据领取时间查询所有用户
        List<YbUser> ybUsers = ybUserMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtil.isEmpty(ybUsers)) {
            throw new CommonException("当前时间段内无用户领取物资");
        }
        List<Long> userIds = ybUsers.stream().map(YbUser::getUserId).collect(Collectors.toSet()).stream().sorted().collect(Collectors.toList());
        //获取所有的用户
        Map<Long, String> userIdForName = userInfoMapper.selectList(new LambdaQueryWrapper<YbUserInfo>()).stream().collect(Collectors.toMap(YbUserInfo::getId, YbUserInfo::getUsername));

        //获取所有的type名称
        List<YbType> ybTypes = ybTypeMapper.selectList(new LambdaQueryWrapper<>());
        Map<Long, String> typeIdForName = ybTypes.stream().collect(Collectors.toMap(YbType::getId, YbType::getTypeName));

        int size = userIds.size();
        size = size + 2;
        List<List<String>> exportList = new ArrayList<>(size);
        List<String> row = null;
        for (Long userId : userIds) {
            row = new ArrayList<>(size);
            String username = userIdForName.get(userId);
            row.add(username);
            setRowMap(row, userId, ybTypes, ybUsers);
            exportList.add(row);
        }

        //合计
        List<String> rowTotal = new ArrayList<>(size);

        List<String> header = new ArrayList<>(size);
        header.add("姓名");
        rowTotal.add("合计");
        for (YbType ybType : ybTypes) {
            Long typeId = ybType.getId();
            String typeName = typeIdForName.get(typeId);
            header.add(typeName);
            BigDecimal quantity = ybUsers.stream().filter(e -> e.getTypeId().equals(typeId)).map(YbUser::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (quantity.compareTo(BigDecimal.ZERO) == 0) {
                rowTotal.add("");
            } else {
                rowTotal.add(quantity.toString());
            }
        }
        exportList.add(0, header);
        exportList.add(rowTotal);

        ExcelWriter writer = ExcelUtil.getWriter(true);

        writer.write(exportList, true);

        String userAgent = request.getHeader("User-Agent");

        String oraFileName = "物资统计报表.xlsx";
        String formFileName=oraFileName;

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");

        // 针对IE或者以IE为内核的浏览器：
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            formFileName = URLEncoder.encode(formFileName, "UTF-8");
        } else {
            // 非IE浏览器的处理：
            formFileName = new String(formFileName.getBytes("UTF-8"), "ISO-8859-1");
        }
        response.setHeader("Content-Disposition",String.format("attachment; filename=\"%s\"", formFileName));
        ServletOutputStream out=response.getOutputStream();
        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);
    }

    @Override
    public Response getUserMaterial(UserMaterialReq userMaterialReq) {
        LambdaQueryWrapper<YbUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(userMaterialReq.getUserId())) {
            lambdaQueryWrapper.eq(YbUser::getUserId, userMaterialReq.getUserId());
        }

        if (ObjectUtil.isNotEmpty(userMaterialReq.getTypeId())) {
            lambdaQueryWrapper.eq(YbUser::getTypeId, userMaterialReq.getTypeId());
        }

        if (ObjectUtil.isNotEmpty(userMaterialReq.getStartDate())) {
            lambdaQueryWrapper.ge(YbUser::getNeedDate, userMaterialReq.getStartDate());
        }

        if (ObjectUtil.isNotEmpty(userMaterialReq.getEndDate())) {
            lambdaQueryWrapper.le(YbUser::getNeedDate, userMaterialReq.getEndDate());
        }
        List<YbUser> list = this.list(lambdaQueryWrapper);
        if (CollectionUtil.isEmpty(list)) {
            return new Response().successWithData(Collections.EMPTY_LIST);
        }

        //查询所有用户
        List<YbUserInfo> ybUserInfos = userInfoMapper.selectList(new LambdaQueryWrapper<>());
        Map<Long, String> usernameMap = ybUserInfos.stream().collect(Collectors.toMap(YbUserInfo::getId, YbUserInfo::getUsername));
        //查询所有物资类型
        List<YbType> ybTypes = ybTypeMapper.selectList(new LambdaQueryWrapper<>());
        Map<Long, String> typeNameMap = ybTypes.stream().collect(Collectors.toMap(YbType::getId, YbType::getTypeName));

        List<YbUserRes> ybUserRes =MapperFactoryUtil.beanLTtoLC(list, YbUserRes.class);
        ybUserRes.forEach(e->{
            e.setTypeName(typeNameMap.get(e.getTypeId()));
            e.setUsername(usernameMap.get(e.getUserId()));
        });

        return new Response().successWithData(ybUserRes);
    }

    private void setRowMap(List<String> row,Long userId,List<YbType> ybTypes,List<YbUser> ybUsers) {
        for (YbType ybType : ybTypes) {
            Long typeId = ybType.getId();
            List<YbUser> typeYbUsers = ybUsers.parallelStream().filter(e -> e.getUserId().equals(userId) && e.getTypeId().equals(typeId)).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(typeYbUsers)) {
                BigDecimal quantity = typeYbUsers.stream().map(YbUser::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
                row.add(quantity.toString());
            } else {
                row.add("");
            }
        }
    }
}
